﻿using DetectScars.Menus;
using DetectScars.model;
using DetectScars.mQLel;
using Modbus.Device;
using Modbus.Extensions.Enron;
using Newtonsoft.Json.Linq;
using ScottPlot.Colormaps;
using ScottPlot.Palettes;
using ScottPlot.PlotStyles;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace DetectScars.common
{
    class PlcControlUtils
    {
        public static string MESSAGE = "1.以上所有单位均为mm（毫米）\r\n" +
            "2.XY轴的速度范围为0~400；Z轴速度范围是0~50；C轴的速度范围为0~30；AB轴的速度范围是0~5\r\n" +
            "3.只有正向点动，反向点动与平台上升下降显示的是状态，需要持续按住\r\n" +
            "4.如果平台在上升或者下降过程中急停，请操作软件取消急停或者机箱屏幕抬升界面取消操作后急停复位\r\n" +
            "5.Y轴的范围是-2000~2250\r\n" +
            "6.Z轴的范围是-240~1010\r\n" +
            "7.A轴(水平轴)的范围是-5~185\r\n" +
            "8.B轴(垂直轴)的范围是-5~185\r\n" +
            "9.以上数据为软件设置，不一定完全符合，可联系工程师进行更改";
        static byte dbBlock = 0;
        static ModbusIpMaster plc;
        public static void setPlc(ModbusIpMaster plc_)
        {
            plc = plc_;
        }
        //读double值
        public static double readValue_d(string adress)
        {
            double b = -1;
            bool lx = false;
            if (adress.StartsWith("I"))
            {
                lx = true;
            }
            char type = adress.ToCharArray()[1];
            adress = adress.Substring(2);
            if (type == 'L')
            {
                ushort startAddress = (ushort)(ushort.Parse(adress) * 4);
                ushort[] inputs = plc.ReadHoldingRegisters(dbBlock, startAddress, 4);
                byte[] bytes = new byte[8];
                bytes[0] = (byte)(inputs[0] & 0xFF);
                bytes[1] = (byte)(inputs[0] >> 8);
                bytes[2] = (byte)(inputs[1] & 0xFF);
                bytes[3] = (byte)(inputs[1] >> 8);
                bytes[4] = (byte)(inputs[2] & 0xFF);
                bytes[5] = (byte)(inputs[2] >> 8);
                bytes[6] = (byte)(inputs[3] & 0xFF);
                bytes[7] = (byte)(inputs[3] >> 8);
                b = BitConverter.ToDouble(bytes, 0);
                //ushort startAddress = (ushort)(ushort.Parse(adress) *4);
                //if (lx)
                //{
                //    ushort[] inputs = plc.ReadHoldingRegisters(dbBlock, startAddress,4);
                //    byte[] bytes = new byte[8];
                //    bytes[0] = (byte)(inputs[0] & 0xFF);
                //    bytes[1] = (byte)(inputs[0]  >> 8);
                //    bytes[2] = (byte)(inputs[1] & 0xFF);
                //    bytes[3] = (byte)(inputs[1] >> 8);
                //    bytes[4] = (byte)(inputs[2] & 0xFF);
                //    bytes[5] = (byte)(inputs[2] >> 8);
                //    bytes[6] = (byte)(inputs[3] & 0xFF);
                //    bytes[7] = (byte)(inputs[3] >> 8);
                //    b = BitConverter.ToDouble(bytes, 0);
                //}
                //else
                //{
                //    ushort[] inputs = plc.ReadInputRegisters(dbBlock, startAddress,4);
                //    byte[] bytes = new byte[8];
                //    bytes[0] = (byte)(inputs[0] & 0xFF);
                //    bytes[1] = (byte)(inputs[0] >> 8);
                //    bytes[2] = (byte)(inputs[1] & 0xFF);
                //    bytes[3] = (byte)(inputs[1] >> 8);
                //    bytes[4] = (byte)(inputs[2] & 0xFF);
                //    bytes[5] = (byte)(inputs[2] >> 8);
                //    bytes[6] = (byte)(inputs[3] & 0xFF);
                //    bytes[7] = (byte)(inputs[3] >> 8);
                //    b = BitConverter.ToDouble(bytes, 0);
                //}
                
            }
            else if (type == 'D')
            {
                ushort startAddress = (ushort)(ushort.Parse(adress) * 2);
                ushort[] inputs = plc.ReadHoldingRegisters(dbBlock, startAddress, 2);
                byte[] bytes = new byte[4];
                bytes[0] = (byte)(inputs[0] & 0xFF);
                bytes[1] = (byte)(inputs[0] >> 8);
                bytes[2] = (byte)(inputs[1] & 0xFF);
                bytes[3] = (byte)(inputs[1] >> 8);
                b = BitConverter.ToInt32(bytes, 0);
                //ushort startAddress = (ushort)(ushort.Parse(adress) * 2);
                //if (lx)
                //{
                //    ushort[] inputs = plc.ReadHoldingRegisters(dbBlock, startAddress, 2);
                //    byte[] bytes = new byte[4];
                //    bytes[0] = (byte)(inputs[0] & 0xFF);
                //    bytes[1] = (byte)(inputs[0] >> 8);
                //    bytes[2] = (byte)(inputs[1] & 0xFF);
                //    bytes[3] = (byte)(inputs[1] >> 8);
                //    b = BitConverter.ToInt32(bytes, 0);
                //}
                //else
                //{
                //    ushort[] inputs = plc.ReadInputRegisters(dbBlock, startAddress, 2);
                //    byte[] bytes = new byte[4];
                //    bytes[0] = (byte)(inputs[0] & 0xFF);
                //    bytes[1] = (byte)(inputs[0] >> 8);
                //    bytes[2] = (byte)(inputs[1] & 0xFF);
                //    bytes[3] = (byte)(inputs[1] >> 8);
                //    b = BitConverter.ToInt32(bytes, 0);
                //}
            }
            else if (type == 'W')
            {
                ushort startAddress = ushort.Parse(adress);
                ushort[] inputs = plc.ReadHoldingRegisters(dbBlock, startAddress, 1);
                //ushort[] inputs = plc.ReadInputRegisters(dbBlock, startAddress, 1);
                b = inputs[0];
            }

            return b;

        }
        //读bool值
        public static bool readValue_b(string adress)
        {
            bool b = false;
            bool lx = false;
            if (adress.StartsWith("I"))
            {
                lx = true;
            }
            char type = adress.ToCharArray()[1];
            adress = adress.Substring(2);
            if (type == 'X')
            {
                ushort s1 = ushort.Parse(adress.Split(".")[0]);
                ushort s2 = ushort.Parse(adress.Split(".")[1]);
                ushort startAddress = (ushort)(s1 * 8 + s2);
                if (lx)
                {
                    startAddress = (ushort)(startAddress + 250);
                }
                else
                {
                    startAddress = (ushort)(startAddress + 200);
                }
                ushort[] inputs = plc.ReadHoldingRegisters(dbBlock, startAddress, 1);
                if (inputs[0]>>16==1)
                {
                    b = true;
                }
                else
                {
                    b = false;
                }
                //if (lx)
                //{
                //    bool[] inputs = plc.ReadCoils(dbBlock, startAddress);
                //    b = inputs[0];
                //}
                //else
                //{
                //    bool[] inputs = plc.ReadInputs(dbBlock, startAddress);
                //    b = inputs[0];
                //}
            }
            return b;
        }

        //写double
        public static void writeValue_d(string adress, double value)
        {
            if (!adress.StartsWith("I"))
            {
                MessageBox.Show("该类型无法写入");
                return;
            }
            LogUtils.WriteLog("写入plc"+ adress+",值："+ value);
            char type = adress.ToCharArray()[1];
            adress = adress.Substring(2);
            if (type == 'L')
            {
                ushort startAddress = (ushort)(ushort.Parse(adress) * 4);
                byte[] bytes = BitConverter.GetBytes(value);
                ushort[] words = new ushort[4];
                words[0] = (ushort)((bytes[1] << 8) | bytes[0]);
                words[1] = (ushort)((bytes[3] << 8) | bytes[2]);
                words[2] = (ushort)((bytes[5] << 8) | bytes[4]);
                words[3] = (ushort)((bytes[7] << 8) | bytes[6]);
                plc.WriteMultipleRegisters(startAddress, words);
            }
            else if (type == 'D')
            {
                byte[] bytes = BitConverter.GetBytes((UInt32)value);
                ushort[] words = new ushort[2];
                ushort startAddress = (ushort)(ushort.Parse(adress)*2);
                words[0] = (ushort)((bytes[1] << 8) | bytes[0]);
                words[1] = (ushort)((bytes[3] << 8) | bytes[2]);
                plc.WriteMultipleRegisters(startAddress, words);
            }
            else if (type == 'W')
            {
                ushort startAddress = ushort.Parse(adress);

                plc.WriteSingleRegister(dbBlock, startAddress, (ushort)value);
            }
            else
            {
                MessageBox.Show("无法写入该类型");
            }
        }
        //写bool
        public static void writeValue_b(string adress,bool bool_)
        {
            bool b = false;
            if (!adress.StartsWith("I"))
            {
                MessageBox.Show("该类型无法写入");
                return;
            }
            LogUtils.WriteLog("写入plc" + adress + ",值：" + bool_);
            char type = adress.ToCharArray()[1];
            adress = adress.Substring(2);
            if (type == 'X')
            {
                ushort s1 = ushort.Parse(adress.Split(".")[0]);
                ushort s2 = ushort.Parse(adress.Split(".")[1]);
                ushort startAddress = (ushort)(s1 * 8 + s2);
                startAddress = (ushort)(startAddress + 250);
                //plc.WriteSingleCoil(startAddress, bool_);
                plc.WriteSingleRegister(dbBlock, startAddress, bool_ == true ?(ushort)1:(ushort)0);
            }
            else
            {
                MessageBox.Show("无法写入非Bool类型");
            }
        }

        //当前轴状态
        //设置点速度1
        public static string getAsixStatus(string axis)
        {
            string msg = "正常";
            if (axis == "Y")
            {
                return msg;
            }
            //停止
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.stop);
            bool status = readValue_b(address);
            if (!status)
            {
                address = PlcDataAddress.getAddress(axis, PlcDataAddress.err);
                status = readValue_b(address);
                if(status)
                {
                    msg = "轴异常";
                }
            }
            else
            {
                msg = "停止";
            }
            return msg;
        }

        //设置点速度1
        public static void setJogSpeed(string axis, double speed)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.v_jog);
            writeValue_d(address, speed);
        }

        //设置绝对速度2
        public static void setAbsoluteSpeed(string axis, double speed)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.v_abs);
            writeValue_d(address, speed);
        }
        //设置相对速度3
        public static void setRelativeSpeed(string axis, double speed)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.v_rel);
            writeValue_d(address, speed);

        }
        //设置绝对位置4
        public static void setAbsolutePosition(string axis, double position)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.p_abs);
            writeValue_d(address, position);
        }
        //设置相对位置5
        public static void setRelativePosition(string axis, double position)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.p_rel);
            writeValue_d(address, position);
        }
        //启动正向点速度6
        public static void startForwardPulse(string axis, bool bl)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.jog_f);
            writeValue_b(address, bl);
        }
        //启动反向点速度7
        public static void startReversePulse(string axis, bool bl)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.jog_b);
            writeValue_b(address, bl);
        }
        //前进至绝对位置
        public static void startAbsoluteRun(string axis, bool bl)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.p_abs_run);
            Thread.Sleep(500);
            writeValue_b(address, bl);
        }
        //前进至相对位置
        public static void startRelativeRun(string axis, bool bl)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.p_rel_run);
            Thread.Sleep(500);
            writeValue_b(address, bl);
        }
        //轴复位8
        public static void axisReset(string axis, bool bl)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.reset);
            writeValue_b(address, bl);
        }
        //轴回零9
        public static void startHome(string axis, bool bl)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.home);
            writeValue_b(address, bl);
        }



        //选择轴回零完成状态10
        public static bool startHomeComStatus(string axis)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.home_don);
            bool status = readValue_b(address);
            return status;
        }

        //轴复位完成状态10
        public static bool axisResetStatus(string axis)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.reset_don);
            bool status = readValue_b(address);
            return status;
        }

        //前进至绝对位置完成状态11
        public static bool startAbsoluteRunComStatus(string axis)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.p_abs_don);
            bool status = readValue_b(address);
            return status;
        }

        //前进至相对位置完成状态12
        public static bool startRelativeRunComStatus(string axis)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.p_rel_don);
            bool status = readValue_b(address);
            return status;
        }


        //获取当前位置13
        internal static double getCurrectPosition(string v)
        {
            string address = PlcDataAddress.getAddress(v, PlcDataAddress.position);
            double value = readValue_d(address);
            return value;
        }
        //轴停止14
        public static void axisStop(string axis, bool bl)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.stop);
            writeValue_b(address, true);
            //Thread.Sleep(500);
            //writeValue_b(address, false);
        }

        //轴停止状态15
        public static bool axisStopStatus(string axis)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.stop_don);
            bool status = readValue_b(address);
            return status;
        }
        //轴错误状态16
        public static bool axisErrStatus(string axis)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.err);
            bool status = readValue_b(address);
            return status;
        }
        //轴错误信息17
        public static double axisErrMsg(string axis)
        {
            string address = PlcDataAddress.getAddress(axis, PlcDataAddress.err_msg);
            double status = readValue_d(address);
            return status;
        }
        public static void startEmergencyStop(bool bl)
        {
            string address = PlcDataAddress.getAddress("", PlcDataAddress.stop);
            writeValue_b(address, bl);
        }

        //    //急停复位
        //    public static void startEmergencyStopReset(bool bl)
        //    {
        //        int s_adr = AxisStruct.emergencyStop_reset_velocity[0];
        //        int b_adr = AxisStruct.emergencyStop_reset_velocity[1];
        //        plc.Write(DataType.DataBlock, dbBlock, s_adr, Convert.ToBoolean(bl), b_adr);
        //    }

        //    //急停状态
        //    public static string startEmergencyStopStatus()
        //    {
        //        string status = "运行中";
        //        int s_adr = AxisStruct.emergencyStop_status_velocity[0];
        //        int b_adr = AxisStruct.emergencyStop_status_velocity[1];
        //        Object? obj = plc.Read(DataType.DataBlock, dbBlock, s_adr, VarType.Bit,b_adr+1);
        //        if (obj != null)
        //        {

        //            if (((BitArray)obj)[b_adr] == true)
        //            {
        //                status = "急停";
        //            }
        //        }
        //        return status;
        //    }


        //    //加紧-复位
        //    public static void clampReset(bool bl)
        //    {
        //        int s_adr = Axis_W.clampReset[0];
        //        int b_adr = Axis_W.clampReset[1];
        //        plc.Write(DataType.DataBlock, dbBlock, s_adr, Convert.ToBoolean(bl), b_adr);
        //    }
        //加紧-速度控制
        public static void clampWZKZ()
        {
            string address = PlcDataAddress.getAddress("W", "wzms");
            writeValue_b(address, true);
            Thread.Sleep(500);
            writeValue_b(address, false);
        }
        //加紧-扭矩模式
        public static void clamNJMS()
        {
            string address = PlcDataAddress.getAddress("W", "njms");
            writeValue_b(address, true);
            Thread.Sleep(500);
            writeValue_b(address, false);
        }
        //加紧-加紧
        public static void clamDown(int zdsd, double nj)
        {
            string address = PlcDataAddress.getAddress("W", "zdsd");
            writeValue_d(address, zdsd);
            nj = Math.Abs(nj);
            //设置扭矩
            address = PlcDataAddress.getAddress("W", "niuju");
            writeValue_d(address, nj);
            //启动
            Thread.Sleep(500);
            address = PlcDataAddress.getAddress("W", "njqd");
            writeValue_b(address, true);
            Thread.Sleep(500);
            writeValue_b(address, false);
        }
        //加紧-松开
        public static void clamUp(int zdsd,double nj)
        {
            string address = PlcDataAddress.getAddress("W", "zdsd");
            writeValue_d(address, zdsd);
            nj = -Math.Abs(nj);
            //设置扭矩
            address = PlcDataAddress.getAddress("W", "niuju");
            writeValue_d(address, nj);
            //启动
            Thread.Sleep(500);
            address = PlcDataAddress.getAddress("W", "njqd");
            writeValue_b(address, true);
            Thread.Sleep(500);
            writeValue_b(address, false);
        }
        //停止
        public static void clamStop()
        {
            //设置扭矩
            string address = PlcDataAddress.getAddress("W", "niuju");
            writeValue_d(address, 0);
            //启动
            Thread.Sleep(500);
            address = PlcDataAddress.getAddress("W", "njqd");
            writeValue_b(address, true);
            Thread.Sleep(500);
            writeValue_b(address, false);
        }
        //加紧-读取扭矩
        public static double clamReadNJ()
        {
            string address = PlcDataAddress.getAddress("W", "niuju");
            double status = readValue_d(address);
            return status;
        }
        //加紧-读取控制状态
        public static string clamReadStatus()
        {
            string msg = "扭矩模式";
            string address = PlcDataAddress.w_mslx;
            double status = readValue_d(address);
            if (status == 8)
            {
                msg = "位置模式";
            }
            return msg;
        }

        //正向旋转
        public static void cZz(int sd,bool bl)
        {
            //设置速度
            string address = PlcDataAddress.getAddress("Y", "velocity");
            writeValue_d(address, sd);
            //启动
            Thread.Sleep(500);
            address = PlcDataAddress.getAddress("Y", "zz");
            writeValue_b(address, bl);
        }
        //反向旋转
        public static void cFz(int sd, bool bl)
        {
            //设置速度
            string address = PlcDataAddress.getAddress("Y", "velocity");
            writeValue_d(address, sd);
            //启动
            Thread.Sleep(500);
            address = PlcDataAddress.getAddress("Y", "fz");
            writeValue_b(address, bl);
        }
        //停止
        public static void cStop()
        {
            string address = PlcDataAddress.getAddress("Y", "fz");
            writeValue_b(address, false);
            address = PlcDataAddress.getAddress("Y", "zz");
            writeValue_b(address, false);
        }
    }
}
